package com.okbihuo.perm.modules.common.logic;

import com.okbihuo.perm.constants.SystemCode;
import com.okbihuo.perm.core.tool.api.BaseException;
import com.okbihuo.perm.core.tool.api.ResultCode;
import com.okbihuo.perm.mod.user.domain.AuthUser;
import com.okbihuo.perm.modules.rwb.qw.config.WxCpConfiguration;
import com.okbihuo.perm.modules.rwb.qw.domain.QwCorpAuth;
import com.okbihuo.perm.modules.rwb.qw.domain.QwCorpMember;
import com.okbihuo.perm.modules.common.domain.RwbSyncLog;
import com.okbihuo.perm.modules.rwb.qw.logic.QwAuthLogic;
import com.okbihuo.perm.modules.rwb.qw.logic.QwCorpCustomerAsyncLogic;
import com.okbihuo.perm.modules.rwb.qw.logic.QwCorpMemberAsyncLogic;
import com.okbihuo.perm.modules.rwb.qw.logic.QwCorpTagAsyncLogic;
import com.okbihuo.perm.modules.rwb.qw.resultcode.WxSdkByGetMembersRequestErrorCode;
import com.okbihuo.perm.modules.rwb.qw.resultcode.WxSdkRequestErrorCode;
import com.okbihuo.perm.modules.rwb.qw.service.QwCorpMemberService;
import com.okbihuo.perm.modules.common.service.RwbSyncLogService;
import com.okbihuo.perm.modules.rwb.sop.logic.QwGroupAsyncLogic;
import com.okbihuo.perm.modules.rwb.sys.domain.RwbSystemSetting;
import com.okbihuo.perm.modules.rwb.sys.service.RwbSystemSettingService;
import com.okbihuo.perm.modules.rwb.utils.PermissionHepler;
import lombok.RequiredArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpUser;
import me.chanjar.weixin.cp.bean.external.WxCpUserExternalGroupChatList;
import me.chanjar.weixin.cp.bean.external.WxCpUserExternalTagGroupList;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 企业异步同步数据
 * @author stt
 */
@Component
@RequiredArgsConstructor
public class RwbSyncLogic {

    private final QwAuthLogic authLogic;
    private final QwCorpTagAsyncLogic tagAsyncLogic;
    private final QwGroupAsyncLogic groupAsyncLogic;
    private final WxCpConfiguration cpConfiguration;
    private final QwCorpMemberService corpMemberService;
    private final QwCorpMemberAsyncLogic memberAsyncLogic;
    private final RwbSyncLogService corpSyncLogService;
    private final RwbSyncLogService syncCorpMemberLogService;
    private final QwCorpCustomerAsyncLogic corpCustomerAsyncLogic;
    private final RwbSystemSettingService systemSettingService;


    /**
     * 同步企业成员
     */
    public static String sync_member = "sync_member";
    /**
     * 同步企业客户
     */
    public static String sync_customer = "sync_customer";
    /**
     * 同步企业客户标签
     */
    public static String sync_tag = "sync_tag";
    /**
     * 同步企业群标签
     */
    public static String sync_group = "sync_group";

    /**
     * 同步公众号粉丝
     */
    public static String sync_fans = "sync_fans";

    /**
     * 根据type检查最新同步记录
     * @param loginUserId
     * @return
     * @throws BaseException
     */
    public void checkRunning(Long loginUserId,String type) throws BaseException {
        //获取企业最新同步记录
        RwbSyncLog newLog = corpSyncLogService.getByNewLogAndType(loginUserId,type);
        if(newLog == null){
            return;
        }
        if(newLog.getSyncEndAt() > System.currentTimeMillis()){
            throw new BaseException(ResultCode.FAILURE,"当前有记录还在同步!");
        }
    }

    /**
     * 根据type检查最新同步记录
     * @param loginUserId
     * @return
     * @throws BaseException
     */
    public RwbSyncLog getByNewLogAndType(Long loginUserId, String type) {
        return corpSyncLogService.getByNewLogAndType(loginUserId,type);
    }

    /**
     * 同步企业成员
     * @param qwUserId
     * @throws BaseException
     */
    public void syncMembers(Long userId,Long qwUserId) throws BaseException {
        //获取账户绑定的企业
        QwCorpAuth corpAuth = authLogic.getCorpAuth(qwUserId);
        if(corpAuth == null){
            throw new BaseException(ResultCode.FAILURE,"未获取到已绑定企业");
        }
        final AuthUser authUser = PermissionHepler.checkUser(corpAuth.getQwUserId());
        //检查企业同步记录
        checkRunning(authUser.getId(),sync_member);
        //获取授权企业
        WxCpService corpService = cpConfiguration.getInteriorService(corpAuth);
        //获取当前时间
        LocalDateTime now = LocalDateTime.now();
        //创建新的同步记录
        RwbSyncLog log = RwbSyncLog.builder()
                .type(sync_member)
                .loginUserId(userId)
                .syncStartAt(now.toInstant(ZoneOffset.of("+8")).toEpochMilli())
                .syncEndAt(now.plusMinutes(getSyncTime()).toInstant(ZoneOffset.of("+8")).toEpochMilli())
                .build();
        syncCorpMemberLogService.saveOrUpdateAndReturn(log);
        //获取所有成员
        List<WxCpUser> userList = new ArrayList<>();
        try {
            userList = corpService.getUserService().listByDepartment(1L, true, null);
        } catch (WxErrorException e) {
            //获取错误code
            int code = e.getError().getErrorCode();
            if(code == 60011){
                throw new BaseException(WxSdkByGetMembersRequestErrorCode.c());
            }
            e.printStackTrace();
        }
        memberAsyncLogic.disposeMember(userList,corpAuth,log);
    }

    /**
     * 同步企业成员
     * @param userId
     * @throws BaseException
     */
    public void syncCustomer(Long userId,Long qwUserId) throws BaseException {
        //获取账户绑定的企业
        QwCorpAuth corpAuth = authLogic.getCorpAuth(qwUserId);
        if(corpAuth == null){
            throw new BaseException(ResultCode.DATA_NOT_FOUND,"未获取到已绑定企业");
        }
        final AuthUser authUser = PermissionHepler.checkUser(corpAuth.getQwUserId());
        //检查企业同步记录
        checkRunning(authUser.getId(),sync_customer);
        //获取授权企业
        WxCpService corpService = cpConfiguration.getInteriorService(corpAuth);
        try {
            //获取企业已激活的裂变成员
            final List<QwCorpMember> members = corpMemberService.listActive(corpAuth.getId());
            //外部联系人externalUserId
            Set<String> set = new HashSet<>();
            for(QwCorpMember member : members){
                //循环获取企业裂变成员的外部联系人
                List<String> externalContacts = corpService.getExternalContactService().listExternalContacts(member.getUserId());
                set.addAll(externalContacts);
            }
            //获取当前时间
            LocalDateTime now = LocalDateTime.now();
            //创建新的同步记录
            RwbSyncLog log = RwbSyncLog.builder()
                    .type(sync_member)
                    .loginUserId(userId)
                    .syncStartAt(now.toInstant(ZoneOffset.of("+8")).toEpochMilli())
                    .syncEndAt(now.plusMinutes(getSyncTime()).toInstant(ZoneOffset.of("+8")).toEpochMilli())
                    .build();
            syncCorpMemberLogService.saveOrUpdateAndReturn(log);
            corpCustomerAsyncLogic.disposeCustomer(set,corpService,corpAuth,log);
        } catch (WxErrorException e) {
            authLogic.updateCorpAuthValidFail(corpAuth.getId());
            throw new BaseException(WxSdkRequestErrorCode.c());
        }
    }

    /**
     * 同步标签
     * @param qwUserId
     * @throws BaseException
     */
    public void syncTag(Long userId,Long qwUserId) throws BaseException {
        //获取账户绑定的企业
        QwCorpAuth corpAuth = authLogic.getCorpAuth(qwUserId);
        if(corpAuth == null){
            throw new BaseException(ResultCode.FAILURE,"未获取到已绑定企业");
        }
        final AuthUser authUser = PermissionHepler.checkUser(corpAuth.getQwUserId());
        //检查企业同步记录
        checkRunning(authUser.getId(),sync_tag);
        //获取授权企业
        WxCpService corpService = cpConfiguration.getInteriorService(corpAuth);
        try {
            //获取微信设置的标签组
            final WxCpUserExternalTagGroupList wxTagList = corpService.getExternalContactService().getCorpTagList(null);
            //获取当前时间
            LocalDateTime now = LocalDateTime.now();
            //创建新的同步记录
            RwbSyncLog log = RwbSyncLog.builder()
                    .type(sync_tag)
                    .loginUserId(userId)
                    .syncStartAt(now.toInstant(ZoneOffset.of("+8")).toEpochMilli())
                    .syncEndAt(now.plusMinutes(getSyncTime()).toInstant(ZoneOffset.of("+8")).toEpochMilli())
                    .build();
            syncCorpMemberLogService.saveOrUpdateAndReturn(log);
            tagAsyncLogic.disposeTag(wxTagList,corpAuth,log);
        } catch (WxErrorException e) {
            authLogic.updateCorpAuthValidFail(corpAuth.getId());
            e.printStackTrace();
        }
    }

    /**
     * 同步企业群
     * @param qwUserId
     * @throws BaseException
     */
    public void syncGroup(Long userId,Long qwUserId) throws BaseException {
        //获取账户绑定的企业
        QwCorpAuth corpAuth = authLogic.getCorpAuth(qwUserId);
        if(corpAuth == null){
            throw new BaseException(ResultCode.FAILURE,"未获取到已绑定企业");
        }
        final AuthUser authUser = PermissionHepler.checkUser(corpAuth.getQwUserId());
        //检查企业同步记录
        checkRunning(authUser.getId(),sync_group);
        //获取授权企业
        WxCpService corpService = cpConfiguration.getInteriorService(corpAuth);
        try {
            //获取企业所有成员
            final List<WxCpUser> userList = corpService.getUserService().listByDepartment(1L, true, null);
            //获取当前时间
            LocalDateTime now = LocalDateTime.now();
            //创建新的同步记录
            RwbSyncLog log = RwbSyncLog.builder()
                    .type(sync_group)
                    .loginUserId(userId)
                    .syncStartAt(now.toInstant(ZoneOffset.of("+8")).toEpochMilli())
                    .syncEndAt(now.plusMinutes(getSyncTime()).toInstant(ZoneOffset.of("+8")).toEpochMilli())
                    .build();
            syncCorpMemberLogService.saveOrUpdateAndReturn(log);
            groupAsyncLogic.disposeGroup(corpService,userList,log,qwUserId);
        } catch (WxErrorException e) {
            authLogic.updateCorpAuthValidFail(corpAuth.getId());
            e.printStackTrace();
        }
    }

    /**
     * 获取系统设置的同步时间
     * @return
     * @throws BaseException
     */
    public Integer getSyncTime() throws BaseException {
        //获取数据库给的同步时间
        final RwbSystemSetting setting = systemSettingService.getByCode(SystemCode.syncTime);
        if(setting == null){
            throw new BaseException(ResultCode.DATA_NOT_FOUND,"未获取到系统设置的同步时间");
        }
        return Integer.valueOf(setting.getValue());
    }

    /**
     * 获取系统设置的同步时间
     * @return
     * @throws BaseException
     */
    public Integer getSyncTimeByFans() throws BaseException {
        //获取数据库给的同步时间
        final RwbSystemSetting setting = systemSettingService.getByCode(SystemCode.syncFansTime);
        if(setting == null){
            throw new BaseException(ResultCode.DATA_NOT_FOUND,"未获取到系统设置的同步时间");
        }
        return Integer.valueOf(setting.getValue());
    }
}
